
package io.renren.utils.util.message;


import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;

import org.apache.log4j.Logger;


/**
 * Concrete subclass of <code>MessageResources</code> that reads message keys
 * and corresponding strings from named property resources in the same manner
 * that <code>java.util.PropertyResourceBundle</code> does.  The
 * <code>base</code> property defines the base property resource name, and
 * must be specified.
 * <p>
 * <strong>IMPLEMENTATION NOTE</strong> - This class trades memory for
 * speed by caching all messages located via generalizing the Locale under
 * the original locale as well.
 * This results in specific messages being stored in the message cache
 * more than once, but improves response time on subsequent requests for
 * the same locale + key combination.
 *
 * @author Clark Liu
 */

public class PropertyMessageResources extends MessageResources {

	static Logger logger = Logger.getLogger(PropertyMessageResources.class.getName());
	
    // ----------------------------------------------------------- Constructors


    /**
     * Construct a new PropertyMessageResources according to the
     * specified parameters.
     *
     * @param factory The MessageResourcesFactory that created us
     * @param config The configuration parameter for this MessageResources
     */
    public PropertyMessageResources(MessageResourcesFactory factory,
                                    String config) {

        super(factory, config);

    }


    /**
     * Construct a new PropertyMessageResources according to the
     * specified parameters.
     *
     * @param factory The MessageResourcesFactory that created us
     * @param config The configuration parameter for this MessageResources
     * @param returnNull The returnNull property we should initialize with
     */
    public PropertyMessageResources(MessageResourcesFactory factory,
                                    String config, boolean returnNull) {

        super(factory, config, returnNull);

    }

    // ------------------------------------------------------------- Properties


    /**
     * The set of locale keys for which we have already loaded messages, keyed
     * by the value calculated in <code>localeKey()</code>.
     */
    protected HashMap locales = new HashMap();


    /**
     * The cache of messages we have accumulated over time, keyed by the
     * value calculated in <code>messageKey()</code>.
     */
    protected HashMap messages = new HashMap();

	/**
	 * The encoding of reading properties file
	 */
	public static String encoding = null;

    // --------------------------------------------------------- Public Methods


    /**
     * Returns a text message for the specified key, for the default Locale.
     * A null string result will be returned by this method if no relevant
     * message resource is found for this key or Locale, if the
     * <code>returnNull</code> property is set.  Otherwise, an appropriate
     * error message will be returned.
     * <p>
     * This method must be implemented by a concrete subclass.
     *
     * @param locale The requested message Locale, or <code>null</code>
     *  for the system default Locale
     * @param key The message key to look up
     */
    public String getMessage(Locale locale, String key) {
		if (logger.isDebugEnabled()) {
			logger.debug("getMessage(" + locale + "," + key + ")");
		}
		
        // Initialize variables we will require
        String localeKey = localeKey(locale);
        String messageKey = null;
        String message = null;
        
            // Load this Locale's messages if we have not done so yet
            loadLocale(localeKey);

            // Check if we have this key for the current locale key
            messageKey = messageKey(localeKey, key);
            synchronized (messages) {
                message = (String) messages.get(messageKey);
                if (message != null) {
                    return convertIso2Utf8(message);
                }
            }
        
        // Return an appropriate error indication
        if (returnNull)
            return (null);
        else
            return ("???" + messageKey(locale, key) + "???");

    }


    // ------------------------------------------------------ Protected Methods


    /**
     * Load the messages associated with the specified Locale key.  For this
     * implementation, the <code>config</code> property should contain a fully
     * qualified package and resource name, separated by periods, of a series
     * of property resources to be loaded from the class loader that created
     * this PropertyMessageResources instance.  This is exactly the same name
     * format you would use when utilizing the
     * <code>java.util.PropertyResourceBundle</code> class.
     *
     * @param localeKey Locale key for the messages to be retrieved
     */
    protected synchronized void loadLocale(String localeKey) {

		if (logger.isDebugEnabled()) {
			logger.debug("loadLocale(" + localeKey + ")");
		}

		// Have we already attempted to load messages for this locale?
		if (locales.get(localeKey) != null) {
			return;
		}

		locales.put(localeKey, localeKey);

		// Set up to load the property resource for this locale key, if we can
		String name = config.replace('.', '/');
		if (localeKey.length() > 0) {
			name += "_" + localeKey;
		}
        
        name += ".properties";
        InputStream is = null;
        Properties props = new Properties();
		if (encoding != null && !"".equals(encoding)) {
			props.setEncoding(encoding);
		}
        // Load the specified property resource
        try {
            is = this.getClass().getClassLoader().getResourceAsStream(name);
            if (logger.isDebugEnabled()) {
            	logger.debug("Loaded message resource file "+ name+".");
            }
            if (is != null) {
                props.load(is);
                is.close();
            }
        } catch (Throwable t) {
            if (is != null) {
                try {
                    is.close();
                } catch (Throwable u) {
                    ;
                }
            }
        }

        // Copy the corresponding values into our cache
        if (props.size() < 1)
            return;
        synchronized (messages) {
            Enumeration names = props.keys();
            while (names.hasMoreElements()) {
                String key = (String) names.nextElement();
                messages.put(messageKey(localeKey, key),
                             props.getProperty(key));
            }
        }

    }
    
    /**
     * This message convert a string from ISO encoding to UTF-8
     * @param isoMsg
     * @return
     */
    private String convertIso2Utf8(String isoMsg) {
    	return isoMsg;
 
//    	String utf8Msg = null;
//	        if (isoMsg != null) {
//	            try {
//	                utf8Msg = new String(isoMsg.getBytes("ISO-8859-1"),"UTF-8");
//	            } catch (UnsupportedEncodingException e) {
//	            }
//	        } 
//        return utf8Msg;
    }
}
